package com.easyUploader.entity.dto;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cn.hutool.extra.spring.SpringUtil;
import com.common.mybaits.CustomPage;
import com.common.util.StringUtil;
import com.easyUploader.property.LocalFileProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

/**
 * @author 大忽悠
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Slf4j
public class BucketDto {
    private Long id;

    /**
     * 存储桶名称
     */
    private String name;

    /**
     * 存储桶类型: 0-只读,1-读写
     */
    private Integer bucketType;

    /**
     * 访问类型: 0-私有,1-公开
     */
    private Integer accessType;

    /**
     * 当前桶下的文件信息
     */
    private List<FileDto> fileDtoList;

    /**
     * 创建者
     */
    private Integer createBy;

    /**
     * 更新者
     */
    private Integer updateBy;

    /**
     * 是否是系统资源: 0-不是,1-是
     */
    private Integer system;

    /**
     * 存储桶下的文件数量
     */
    private Integer fileNum;

    /**
     * 存储桶相对于baseDir的路径,如: system/private
     */
    private String path;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;


    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime updateTime;

    public static List<FileDto> listFileInfo(LocalFileProperty localFileProperty,String bucketName, String dir, CustomPage customPage) {
        String relativePath=StringUtil.pathMerge(false,bucketName,dir);
        String dirPath = localFileProperty.getDirPath(bucketName,dir);
        File file = new File(dirPath);
        if(!file.exists()){
            return Collections.emptyList();
        }
        List<FileDto> fileDtoList=new ArrayList<>();
        //是文件
        if(file.isFile()){
            fileDtoList.add(buildFileDto(file,relativePath));
        }else {
            //是目录
            doBuildDirFileInfoList(file,fileDtoList,customPage,relativePath,Boolean.FALSE);
        }
        return fileDtoList;
    }

    private static void doBuildDirFileInfoList(File file, List<FileDto> fileDtoList, CustomPage customPage, String relativePath,Boolean shareFile) {
        File[] listFiles = file.listFiles();
        //启用分页查询
        Integer pageNum=0;
        Integer pageSize=listFiles.length;
        Integer startIndex=pageNum;
        Integer endIndex=pageSize;

        if(CustomPage.enable(customPage)){
            pageNum=customPage.getPageNum();
            pageSize=customPage.getPageSize();
            startIndex=(pageNum-1)*pageSize;
            if(startIndex>=listFiles.length){
                return;
            }
            endIndex=startIndex+pageSize;
            if(endIndex>=listFiles.length){
                endIndex=listFiles.length-1;
            }
        }

        for (int i = startIndex; i < endIndex; i++) {
            if(!shareFile){
                fileDtoList.add(buildFileDto(listFiles[i],relativePath));
            }else {
                fileDtoList.add(buildShareFileDto(listFiles[i],relativePath));
            }
        }
    }

    public void buildFileInfo(LocalFileProperty localFileProperty) {
        String bucketFilePath=localFileProperty.getBucketPath(name);
        buildFileDtoList(bucketFilePath);
    }

    private static FileDto buildFileDto(File file,String relativePath) {
        return FileDto.builder().size(file.isDirectory() ? file.listFiles().length : file.length())
                .relativePath(relativePath).name(file.getName()).isDir(file.isDirectory())
                .visitUrl(SpringUtil.getBean(LocalFileProperty.class)
                                .getFileOrDirVisitUrlByRelativePath(
                                        StringUtil.pathMerge(false,relativePath,file.getName()))).build();
    }


    public List<FileDto> listShareFiles(String dir, CustomPage customPage,LocalFileProperty localFileProperty) {
        String relativePath=StringUtil.pathMerge(false,LocalFileProperty.DEFAULT_BUCKET,dir);
        String dirPath = localFileProperty.getShareDirOrFilePath(dir);
        File file = new File(dirPath);
        if(!file.exists()){
            return Collections.emptyList();
        }
        List<FileDto> fileDtoList=new ArrayList<>();
        //是文件
        if(file.isFile()){
            fileDtoList.add(buildShareFileDto(file,relativePath));
        }else {
            //是目录
            doBuildDirFileInfoList(file,fileDtoList,customPage,relativePath,Boolean.TRUE);
        }
        return fileDtoList;
    }

    public void buildShareFileInfo(LocalFileProperty localFileProperty) {
        String bucketFilePath=localFileProperty.getShareBucketPath(name);
        buildFileDtoList(bucketFilePath,Boolean.TRUE);
    }


    private void buildFileDtoList(String bucketFilePath){
        buildFileDtoList(bucketFilePath,Boolean.FALSE);
    }

    private void buildFileDtoList(String bucketFilePath,Boolean shareFile) {
        File bucket = new File(bucketFilePath);
        File[] files = bucket.listFiles();
        if(!bucket.exists() || files==null){
            return;
        }
        fileDtoList=new ArrayList<>(files.length);
        for (File file : files) {
            if(!shareFile){
                fileDtoList.add(buildFileDto(file,name));
            }else {
                fileDtoList.add(buildShareFileDto(file,name));
            }
        }
        if(ObjectUtils.isEmpty(fileDtoList)){
            fileDtoList=null;
        }
    }

    private static FileDto buildShareFileDto(File file, String relativePath) {
        return FileDto.builder().size(file.isDirectory() ? file.listFiles().length : file.length())
                .relativePath(relativePath).name(file.getName()).isDir(file.isDirectory())
                .visitUrl(SpringUtil.getBean(LocalFileProperty.class)
                        .getShareFileOrDirVisitUrlByRelativePath(
                                StringUtil.pathMerge(false,relativePath,file.getName()))).build();
    }
}
